<?php
/**
 * PrynLib
 * @copyright 2007-2009 Prynel
 * @author Olivier ROGER <roger.olivier@gmail.com>
 * @category libPrynel
 * @package File
 * @version $Revision: 80 $
 */

/**
 * Gestion d'accès au fichier
 * @category libPrynel
 * @package File
 * @version 1.0.1 
 * @author Olivier ROGER <roger.olivier@gmail.com>
 * @copyright  2007-2009 Prynel
 *       
 *
 */



class File_FileManager
{
	
	const READ 				= 'r';
	const READ_WRITE 		= 'r+';
	const WRITE				= 'w';
	const READ_WRITE_RESET 	= 'w+';
	const ADD 				= 'a';
	const READ_WRITE_ADD 	= 'a+';
	
	/**
	 * Ressource de fichier
	 * @access private
	 * @var ressource
	 */
	private $fileHandler;
	
	/**
	 * Chemin vers le fichier d'origine
	 * @access protected
	 * @var string
	 */
	protected $pathToFile;
	
	/**
	 * Détermine is un fichier doit être réecris ou non
	 * @access public
	 * @var boolean
	 */
	public $overwrite;
	
	/**
	 * Constructeur
	 *
	 * @param string $file chemin vers le fichier
	 */
	public function __construct($file)
	{
		$this->pathToFile = $file;
		$this->overwrite  = true;
	}
	
	/**
	 * Vérifie si le fichier est un fichier
	 *
	 * @return boolean
	 */
	public function isFile()
	{
		if(is_file($this->pathToFile))
			return true;
		else
			return false;
	}
	/**
	 * Ouvre le fichier demandé
	 *
	 * @param string $mode Mode d'ouverture
	 * @return boolean
	 */
	public function open($mode)
	{
		if(file_exists($this->pathToFile) || ($mode != self::READ && $mode != self::READ_WRITE))
		{
			if($this->isFile() || ($mode != self::READ && $mode != self::READ_WRITE))
			{
				$this->fileHandler = fopen($this->pathToFile,$mode);
				if(is_resource($this->fileHandler))
					return true;
				else
					return false;
			}
			else
			{
				throw new Util_ExceptionHandler($this->pathToFile.' n\'est pas un fichier valide');
			}
		}
		else
		{
			throw new Util_ExceptionHandler('Le fichier '.$this->pathToFile.' n\'existe pas');
		}
	}
	
	/**
	 * Ferme le fichier
	 *
	 * @return boolean
	 */
	public function close()
	{
		if(is_resource($this->fileHandler))
		{
			return fclose($this->fileHandler);
		}
	}
	
	/**
	 * Lit le contenu d'un fichier
	 *
	 * @return mixed
	 */
	public function read()
	{
		if(!is_resource($this->fileHandler))
			$this->open(self::READ);
		if(is_readable($this->pathToFile))
			return fread($this->fileHandler,filesize($this->pathToFile));
		return false;
	}
	
	/**
	 * Lit un fichier ligne par ligne
	 *
	 * @param int $line2read Ligne à lire dans le fichier
	 * @return mixed
	 */
	public function readLine($line2read=null)
	{
		if(!is_resource($this->fileHandler))
		{
			$this->open(self::READ);
		}
		if($line2read == null)
		{
			$arrLine = array();
			while(!feof($this->fileHandler))
			{
				if($data = fgets($this->fileHandler,4096))
					$arrLine[] = $data;
			}
			return $arrLine;
		}
		else
		{
			$i=1;
			while(!feof($this->fileHandler))
			{
				$buffer = fgets($this->fileHandler,4096);
				if($i==$line2read && $buffer!==FALSE)
					return $buffer;
				$i++;
			}
		}
		return false;
	}
	
	/**
	 * Recherche si une chaine est présente dans un fichier
	 *
	 * @param string $toSearch
	 * @return mixed
	 */
	public function search($toSearch)
	{
		$search = $this->read();
		return stripos($search,$toSearch);
	}
	
	/**
	 * Ecrit dans le fichier
	 *
	 * @param string $contenu
	 * @return mixed False si erreur , nombre d'octec sinon
	 */
	public function write($contenu)
	{
		if(is_resource($this->fileHandler) && is_writable($this->pathToFile))
		{
			return fwrite($this->fileHandler,$contenu);
		}
		return false;
	}
	
	/**
	 * Ecrit une ligne
	 *
	 * @param string $ligne Ligne à écrire
	 * @param string $endLine caractère de fin de ligne
	 * @return mixed False si erreur , nombre d'octec sinon
	 */
	public function writeLine($line,$endLine="\n")
	{
		if(is_resource($this->fileHandler) && is_writable($this->pathToFile))
		{
			return fwrite($this->fileHandler,$line.$endLine);
		}
		return false;
	}
	
	/**
	 * Insert une ligne dans un fichier à l'endroit voulu
	 *
	 * @param string $line Ligne à écrire
	 * @param int $numLineInsert Indice de ligne pour insérer la nouvelle ligne
	 */
	public function insertLine($line,$numLineInsert)
	{
		$arrLineFile = $this->readLine();
		fseek($this->fileHandler,0);
		$taille = count($arrLineFile)+1;
		if($taille>$numLineInsert)
		{
			for($i=0;$i<$taille;$i++)
			{
				if($i==$numLineInsert-1)
				{
					$this->writeLine($line);
				}
				$this->write($arrLineFile[$i]);
			}
		}
	}
	
	/**
	 * Récupère les information du fichier
	 *
	 * @return array
	 */
	public function getInfo()
	{
		$arrInfo = array();
		$arrInfo['extension'] = File_Util::getExtension($this->pathToFile);
		$arrInfo['name']	  = File_Util::getNameFromPath($this->pathToFile);
		$arrInfo['size']	  = filesize($this->pathToFile);
		if($this->isFile($this->pathToFile))
			$arrInfo['type']  = 'file';
		else
			$arrInfo['type']  = 'dir';
		return $arrInfo;
	}
	
	/**
	 * Copie un fichier vers un dossier
	 *
	 * @param string $pathToCopy Chemin complet du fichier de copié
	 * @param boolean $ecrase
	 * @return unknown
	 */
	public function copy($pathToCopy)
	{
		$pathToCopy = $this->preparePath($pathToCopy,'copy');
		if(!$this->overwrite)
		{
			if(!file_exists($pathToCopy))
			{
				return false;
			}
			else
			{
				return copy($this->pathToFile,$pathToCopy);
			}
		}
		else
		{
			return copy($this->pathToFile,$pathToCopy);
		}
	}
	
	/**
	 * Déplace un fichier vers un dossier
	 *
	 * @param string $pathToMove Chemin complet du fichier une fois déplacé
	 * @return boolean
	 */
	public function move($pathToMove)
	{
		$pathToMove = $this->preparePath($pathToMove,'copy');
		if(!$this->overwrite)
		{
			if(file_exists($pathToMove))
			{
				return false;
			}
			else
			{
				return rename($this->pathToFile,$pathToMove);
			}
		}
		else
		{
			if(file_exists($pathToMove))
				unlink($pathToMove);
			return rename($this->pathToFile,$pathToMove);
		}
	}
	
	/**
	 * Prépare le path donné pour être correct (slash, espace ...)
	 *
	 * @param string $path
	 * @param string $mode Mode de préparation (copy,move ...)
	 * @return string
	 */
	private function preparePath($path,$mode)
	{
		$path = trim($path);
		switch($mode)
		{
			case 'copy' :
				if($path[0]=='/')
				{
					echo $path = substr($path,1);
				}
				break;
		}
		return $path;
	}
	
	public function __destruct()
	{
		$this->close();
	}
}
 ?>